package com.aizuda.boot.modules.flw.service.impl;

import com.aizuda.boot.config.properties.FeiShuConfigProperties;
import com.aizuda.boot.modules.business.contract.entity.ContractEntity;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.business.contract.service.ContractService;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.feishu.FeiShuApproval;
import com.aizuda.boot.modules.business.feishu.domain.ApprovalParam;
import com.aizuda.boot.modules.business.feishu.domain.approval.SynchronizationApprovalDTO;
import com.aizuda.boot.modules.business.negotiation.annotation.ProcessNegotiation;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationInstanceMapper;
import com.aizuda.boot.modules.business.negotiation.service.ContractNegotiationTaskService;
import com.aizuda.boot.modules.common.MessageEvent;
import com.aizuda.boot.modules.common.constant.enums.ContractStatusEnum;
import com.aizuda.boot.modules.common.constant.enums.FeiShuInstanceStatus;
import com.aizuda.boot.modules.common.constant.enums.FeiShuTaskStatus;
import com.aizuda.boot.modules.common.constant.enums.SystemFieldsEnum;
import com.aizuda.boot.modules.flw.entity.*;
import com.aizuda.boot.modules.flw.entity.dto.*;
import com.aizuda.boot.modules.flw.entity.vo.*;
import com.aizuda.boot.modules.flw.flow.FlowForm;
import com.aizuda.boot.modules.flw.flow.FlowHelper;
import com.aizuda.boot.modules.flw.mapper.FlowlongMapper;
import com.aizuda.boot.modules.flw.service.*;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.system.service.ISysSSEService;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.bpm.engine.FlowDataTransfer;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.TaskService;
import com.aizuda.bpm.engine.core.Execution;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.core.FlowLongContext;
import com.aizuda.bpm.engine.core.enums.PerformType;
import com.aizuda.bpm.engine.core.enums.ProcessType;
import com.aizuda.bpm.engine.core.enums.TaskType;
import com.aizuda.bpm.engine.entity.*;
import com.aizuda.bpm.engine.model.ModelHelper;
import com.aizuda.bpm.engine.model.NodeAssignee;
import com.aizuda.bpm.engine.model.NodeModel;
import com.aizuda.bpm.engine.model.ProcessModel;
import com.aizuda.bpm.mybatisplus.mapper.FlwExtInstanceMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwTaskActorMapper;
import com.aizuda.common.toolkit.JacksonUtils;
import com.aizuda.core.api.ApiAssert;
import com.aizuda.core.api.PageParam;
import com.aizuda.service.web.UserSession;
import com.alibaba.fastjson.JSON;
import com.baomidou.kisso.starter.KissoProperties;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程任务 服务实现类
 *
 * @author 青苗
 * @since 2023-12-11
 */
@Slf4j
@Service
@AllArgsConstructor
public class FlwProcessTaskServiceImpl implements IFlwProcessTaskService {
    private FlowlongMapper flowlongMapper;
    private FlwExtInstanceMapper extInstanceMapper;
    private FlowLongEngine flowLongEngine;
    private IFlwProcessApprovalService flwProcessApprovalService;
    private IFlwProcessFormService flwProcessFormService;
    private IFlwFormTemplateService flwFormTemplateService;
    private IFlwProcessConfigureService flwProcessConfigureService;
    private ISysUserService sysUserService;
    private ISysSSEService sseService;
    private ContractNegotiationTaskService contractNegotiationTaskService;
    @Lazy
    private ContractService contractService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private ContractNegotiationInstanceMapper contractNegotiationInstanceMapper;

    @Resource
    private FeiShuApproval feiShuApproval;

    @Resource
    private FeiShuConfigProperties feiShuConfigProperties;

    @Resource
    private KissoProperties kissoProperties;

    @Resource
    private FlwTaskActorMapper taskActorMapper;

    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;

    @Override
    public Page<PendingClaimTaskVO> pagePendingClaim(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<PendingClaimTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPagePendingClaim(page, dto);
    }

    @Override
    public Page<PendingApprovalTaskVO> pagePendingApproval(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<PendingApprovalTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPagePendingApproval(page, dto);
    }

    @Override
    public Page<PendingApprovalTaskVO> pageAllPendingApproval(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<PendingApprovalTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPageAllPendingApproval(page, dto);
    }

    @Override
    public Page<ProcessTaskVO> pageMyApplication(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<ProcessTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPageMyApplication(page, dto);
    }

    @Override
    public Page<ProcessTaskVO> pageMyReceived(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<ProcessTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPageMyReceived(page, dto);
    }

    @Override
    public Page<ProcessTaskVO> pageApproved(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<ProcessTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPageApproved(pageParam.page(), dto);
    }

    @Override
    public Page<PendingApprovalTaskVO> pageAllApproved(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = this.getProcessTaskDTO(pageParam);
        Page<PendingApprovalTaskVO> page = pageParam.page();
        page.setSearchCount(false);
        return flowlongMapper.selectPageAllApproved(page, dto);
    }

    @Override
    public TaskApprovalVO approvalInfo(ProcessInfoDTO dto) {
        final Long instanceId = dto.getInstanceId();
        FlwHisInstance hisInstance = flowLongEngine.queryService().getHistInstance(instanceId);
        ApiAssert.isEmpty(hisInstance, "未发现指定审批流程");
        TaskApprovalVO vo = new TaskApprovalVO();
        vo.setInstanceId(hisInstance.getId());
        vo.setInstanceState(hisInstance.getInstanceState());
        vo.setTaskId(dto.getTaskId());
        vo.setCreateId(hisInstance.getCreateId());
        vo.setCreateBy(hisInstance.getCreateBy());
        vo.setCreateTime(hisInstance.getCreateTime());

        // 获取当前流程模型
        FlwExtInstance extInstance = extInstanceMapper.selectById(instanceId);
        vo.setModelContent(extInstance.getModelContent());
        ProcessModel processModel = extInstance.model();

        // 表单配置权限
        if (null != dto.getTaskId()) {
            FlwTask flwTask = this.getFlwTask(dto.getTaskId());
            NodeModel nodeModel = processModel.getNode(flwTask.getTaskKey());
            Map<String, Object> extendConfig = nodeModel.getExtendConfig();
            if (null != extendConfig) {
                // 表单配置内容
                Object formConfig = extendConfig.get("formConfig");
                if (null != formConfig) {
                    vo.setFormConfig(formConfig);
                }
            }
            vo.setTaskType(flwTask.getTaskType());
            vo.setActionUrl(nodeModel.getActionUrl());

            // 设置按钮控制参数
            vo.setAllowTransfer(nodeModel.getAllowTransfer());
            vo.setAllowAppendNode(nodeModel.getAllowAppendNode());
            vo.setAllowRollback(nodeModel.getAllowRollback());
            vo.setAllowCc(nodeModel.getAllowCc());
            vo.setRejectStrategy(nodeModel.getRejectStrategy());
        }

        FlwProcessConfigure configure = flwProcessConfigureService.getByProcessId(hisInstance.getProcessId());
        if (null != configure) {
            boolean searchFormContent = true;

            // 流程设置
            vo.setProcessSetting(configure.getProcessSetting());

            // 表单设置
            if (ProcessType.business.eq(extInstance.getProcessType())) {
                // 业务流程，加载表单模板内容
                FlwFormTemplate formTemplate = flwFormTemplateService.getByConfigure(configure.getProcessForm());
                ApiAssert.fail(null == formTemplate, "未发现指定业务流程表单模板");
                vo.setFormTemplate(formTemplate);
                if (Objects.equals(formTemplate.getType(), 1)) {
                    // 系统表单情况
                    searchFormContent = false;
                }
            }

            // 表单内容
            if (searchFormContent) {
                vo.setFormContent(this.formContent(instanceId, hisInstance.getParentInstanceId()));
            }
        }

        // 渲染节点列表
        Map<String, Object> formArgs = null;
        if (null != vo.getFormContent()) {
            Map<String, Object> formMap = JacksonUtils.readMap(vo.getFormContent());
            if (null != formMap) {
                formArgs = (Map<String, Object>) formMap.get("formData");
            }
        }
        // Fix null pointer exception: use full constructor to properly initialize engine field
        final Execution execution = new Execution(flowLongEngine, processModel, FlowHelper.getFlowCreator(), hisInstance, formArgs);
        final FlowLongContext flowLongContext = flowLongEngine.getContext();
        final NodeModel nodeModel = processModel.getNodeConfig();
        Map<String, Integer> renderNodes = new HashMap<>();
        List<String> usedNodeKeys = ModelHelper.getAllUsedNodeKeys(flowLongContext, execution, nodeModel, hisInstance.getCurrentNodeKey());
        for (String nodeKey : usedNodeKeys) {
            // 已执行节点
            renderNodes.put(nodeKey, 0);
        }

        // 审批记录列表
        List<FlwProcessApproval> processApprovals = flwProcessApprovalService.listByInstanceId(instanceId);

        // 待执行节点列表
        List<String> pendingNodeKeys = new ArrayList<>();

        // 追加当前正在审核任务记录
        if (null == hisInstance.getEndTime()) {
            List<FlwTask> flwTaskList = flowLongEngine.queryService().getTasksByInstanceId(instanceId);
            if (CollectionUtils.isNotEmpty(flwTaskList)) {
                FlwTask flwTask;
                if (null != dto.getTaskId() && flwTaskList.size() > 1) {
                    // 并行分支情况，找到指定任务 ID
                    flwTask = flwTaskList.stream().filter(t -> Objects.equals(dto.getTaskId(), t.getId())).findFirst().get();
                } else {
                    flwTask = flwTaskList.get(0);
                }
                FlwProcessApproval fpa = new FlwProcessApproval();
                fpa.setInstanceId(instanceId);
                fpa.setTaskId(flwTask.getId());
                fpa.setTaskName(flwTask.getTaskName());
                fpa.setType(-1);
                Integer performType = flwTask.getPerformType();
                if (!(PerformType.timer.eq(performType) && PerformType.trigger.eq(performType))) {
                    // 排除 定时器 & 触发器
                    ApprovalContent content = new ApprovalContent();
                    if (PerformType.countersign.eq(performType)) {
                        // 会签情况
                        flowLongEngine.queryService().getActiveTaskActorsByInstanceId(flwTask.getInstanceId()).ifPresent(content::appendNodeAssignee);
                    } else {
                        // 其它
                        flowLongEngine.queryService().getActiveTaskActorsByTaskId(flwTask.getId()).ifPresent(content::appendNodeAssignee);
                    }
                    fpa.setContent(content);
                }
                processApprovals.add(fpa);

                // 正在执行节点
                for (FlwTask ft : flwTaskList) {
                    renderNodes.put(ft.getTaskKey(), 1);
                    pendingNodeKeys.add(ft.getTaskKey());
                }
            }
        } else {
            // 流程结束，渲染最终完成结束节点
            renderNodes.put(hisInstance.getCurrentNodeKey(), 0);
        }

        // 找到未记录【执行节点】的办理任务，获取可能在分支中已执行节点【排除包含正在执行节点的历史数据】
        processApprovals.stream().filter(t -> Objects.equals(3, t.getType()) && !usedNodeKeys.contains(t.getTaskKey())).map(t -> ModelHelper.getAllUsedNodeKeys(flowLongContext, execution, nodeModel, t.getTaskKey())).filter(nodeKeys -> nodeKeys.stream().noneMatch(pendingNodeKeys::contains)).forEach(nodeKeys -> nodeKeys.forEach(nodeKey -> renderNodes.put(nodeKey, 0)));

        // 设置渲染节点信息
        vo.setRenderNodes(renderNodes);

        // 处理审批记录中的createBy字段，将用户名替换为真实姓名
        processApprovals = processApprovalRealNames(processApprovals);

        vo.setProcessApprovals(processApprovals);

        //设置所有节点信息
        List<NodeModel> nodeModelsMapList = getNextNodeList(NodeRendering.Req.builder().instanceId(dto.getInstanceId()).taskId(dto.getTaskId()).formData(formArgs).build());
        vo.setNextNodeModels(nodeModelsMapList);
        return vo;
    }

    /**
     * 查询流程表单内容
     * <p>
     * 普通流程，表单填写内容，子流程需要获取主流程表单
     * </p>
     */
    private String formContent(Long instanceId, Long parentInstanceId) {
        // 普通流程，表单填写内容，子流程需要获取主流程表单
        FlwProcessForm flwProcessForm;
        if (null != parentInstanceId) {
            flwProcessForm = flwProcessFormService.getByInstanceId(parentInstanceId);
        } else {
            flwProcessForm = flwProcessFormService.getByInstanceId(instanceId);
        }
        return null == flwProcessForm ? null : flwProcessForm.getContent();
    }

    @Override
    public List<Map<String, String>> listPreviousNodes(Long taskId) {
        FlwTask flwTask = this.getFlwTask(taskId);
        ProcessModel processModel = flowLongEngine.runtimeService().getProcessModelByInstanceId(flwTask.getInstanceId());
        List<String> nodeKeys = ModelHelper.getAllPreviousNodeKeys(processModel.getNode(flwTask.getTaskKey()));
        List<Map<String, String>> mapList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(nodeKeys)) {
            for (String nodeKey : nodeKeys) {
                // 模型中找到可回退历史节点信息
                NodeModel nodeModel = processModel.getNode(nodeKey);
                if (null != nodeModel) {
                    Map<String, String> map = new HashMap<>();
                    map.put("nodeName", nodeModel.getNodeName());
                    map.put("nodeKey", nodeModel.getNodeKey());
                    mapList.add(map);
                }
            }
        }
        return mapList;
    }

    @Override
    public Map<String, Object> listNextNodes(NextNodesDTO dto) {
        FlwInstance instance = flowLongEngine.queryService().getInstance(dto.getInstanceId());
        ApiAssert.fail(null == instance, "当前流程实例不存在");
        FlwExtInstance extInstance = flowLongEngine.queryService().getExtInstance(dto.getInstanceId());
        NodeModel rootNodeModel = extInstance.model().getNodeConfig();
        // 修复空指针异常：使用包含engine参数的构造函数
        Execution execution = new Execution(flowLongEngine, extInstance.model(), FlowHelper.getFlowCreator(), instance, dto.getArgs());
        execution.setEngine(flowLongEngine);
        Map<String, Object> nodeModelsMap = new HashMap<>();
        List<NodeModel> nodeModels = ModelHelper.getNextChildNodes(flowLongEngine.getContext(), execution, rootNodeModel, instance.getCurrentNodeKey());
        if (null != nodeModels) {
            nodeModelsMap.put("nodeType", getNodeType(nodeModels));
            nodeModelsMap.put("nodeModels", nodeModels.stream().map(NodeModel::cloneBaseInfo).toList());
            nodeModelsMap.put("nodeCount", nodeModels.size());
        } else {
            nodeModelsMap.put("nodeType", 0);
            nodeModelsMap.put("nodeModels", new ArrayList<>());
            nodeModelsMap.put("nodeCount", 0);
        }
        return nodeModelsMap;
    }

    @Override
    public Map<String, Object> listNextNodesAssigneeMap(NextNodesDTO dto) {
        FlwInstance instance = flowLongEngine.queryService().getInstance(dto.getInstanceId());
        ApiAssert.fail(null == instance, "当前流程实例不存在");
        FlwExtInstance extInstance = flowLongEngine.queryService().getExtInstance(dto.getInstanceId());
        NodeModel rootNodeModel = extInstance.model().getNodeConfig();
        // 修复空指针异常：使用包含engine参数的构造函数
        Execution execution = new Execution(flowLongEngine, extInstance.model(), FlowHelper.getFlowCreator(), instance, dto.getArgs());

        // 获取下一个节点列表
        List<NodeModel> nodeModels = ModelHelper.getNextChildNodes(flowLongEngine.getContext(), execution, rootNodeModel, instance.getCurrentNodeKey());

        Map<String, Object> result = new HashMap<>();
        Map<String, Object> assigneeMap = new HashMap<>();

        if (null != nodeModels && !nodeModels.isEmpty()) {
            // 对每个下一个节点解析其assigneeMap
            for (NodeModel nodeModel : nodeModels) {
                parseNodeAssignee(nodeModel, assigneeMap);
            }

            result.put("nodeType", getNodeType(nodeModels));
            result.put("assigneeMap", assigneeMap);
            result.put("nodeCount", nodeModels.size());
        } else {
            result.put("nodeType", 0);
            result.put("assigneeMap", assigneeMap);
            result.put("nodeCount", 0);
        }

        return result;
    }

    private static int getNodeType(List<NodeModel> nodeModels) {
        // 1，普通审批
        int nodeType = 1;
        if (nodeModels.size() > 1) {
            // 判断是否为条件分支，根据父节点确定分支类型
            NodeModel nextParentNode = nodeModels.get(0).getParentNode();
            if (nextParentNode.conditionNode()) {
                // 4，条件分支
                nodeType = 4;
            } else if (nextParentNode.parallelNode()) {
                // 8，并行分支
                nodeType = 8;
            } else if (nextParentNode.inclusiveNode()) {
                // 9，包容分支
                nodeType = 9;
            }
        }
        return nodeType;
    }

    @Override
    public boolean viewed(Long taskId) {
        return flowLongEngine.taskService().viewTask(taskId, FlowHelper.getFlowCreator());
    }

    /**
     * 获取流程任务DTO
     */
    private ProcessTaskDTO getProcessTaskDTO(PageParam<ProcessTaskDTO> pageParam) {
        ProcessTaskDTO dto = pageParam.getData();
        if (null == dto) {
            dto = new ProcessTaskDTO();
        }
        UserSession userSession = UserSession.getLoginInfo();
        dto.setCreateId(userSession.getUserId());
        return dto;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean reclaim(Long taskId, FlowCreator flowCreator) {
        TaskService taskService = flowLongEngine.taskService();
        return taskService.reclaimTask(taskId, flowCreator).isPresent();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean claim(Long taskId, FlowCreator flowCreator) {
        TaskService taskService = flowLongEngine.taskService();
        boolean claimResult = null != taskService.claimRole(taskId, flowCreator);

        // 如果认领成功，尝试处理协商流程相关逻辑
        if (claimResult) {
            try {
                // 注入协商任务服务并处理协商逻辑
                if (contractNegotiationTaskService != null) {
                    contractNegotiationTaskService.handleNegotiationTaskClaim(taskId, flowCreator);
                }
            } catch (Exception e) {
                // 协商逻辑处理失败不影响认领结果，只记录日志
                log.warn("处理协商任务认领逻辑失败 - taskId: {}, userId: {}", taskId, flowCreator.getCreateId(), e);
            }
        }

        return claimResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean revoke(ProcessApprovalDTO dto, FlowCreator flowCreator) {
        FlwInstance flwInstance = flowLongEngine.queryService().getInstance(dto.getInstanceId());
        ApiAssert.fail(null == flwInstance, "流程实例已结束");
        FlwProcessConfigure configure = flwProcessConfigureService.getByProcessId(flwInstance.getProcessId());
        if (null != configure && null != configure.getProcessSetting()) {
            ApiAssert.fail(!Objects.equals(true, configure.getProcessSetting().getAllowRevocation()), "该审批流程不允许撤回");
        }
        FlowHelper.setProcessApprovalOpinion(dto.getContent());
        if (dto.isTermination()) {
            // 发起人撤回终止
            flowLongEngine.runtimeService().revoke(dto.getInstanceId(), flowCreator);
            return true;
        }

        // 发起人撤回任务
        FlwHisTask fht = flowLongEngine.queryService().getStartTaskByInstanceId(dto.getInstanceId());
        ApiAssert.fail(null == fht || fht.startNode(), "发起人节点不允许继续撤回");
        TaskService taskService = flowLongEngine.taskService();
        return taskService.withdrawTask(fht.getId(), flowCreator).isPresent();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean execute(ExecuteTaskDTO dto) {
        if (StringUtils.isNotBlank(dto.getOpinion())) {
            FlowHelper.setProcessApprovalOpinion(dto.getOpinion());
        }
        return flowLongEngine.executeTask(dto.getTaskId(), FlowHelper.getFlowCreator(), dto.getArgs());
    }

    @Override
    public List<FlwHisTaskVO> listHisTaskByInstanceId(Long instanceId) {
        List<FlwHisTaskVO> voList = flowlongMapper.selectListHisTaskByInstanceId(instanceId);
        if (CollectionUtils.isNotEmpty(voList)) {
            List<FlwHisTaskActorVO> actorList = flowlongMapper.selectListHisTaskActorVOByInstanceId(instanceId);
            if (CollectionUtils.isNotEmpty(actorList)) {
                voList.forEach(t -> t.setActorList(actorList.stream().filter(v -> Objects.equals(v.getTaskId(), t.getId())).collect(Collectors.toList())));
            }
        }
        return voList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean reject(RejectTaskDTO dto) {
        FlwTask flwTask = this.checkFlwTaskById(dto.getTaskId());
        FlowHelper.setProcessApprovalOpinion(dto.getReason());
        return flowLongEngine.executeRejectTask(flwTask, dto.getNodeKey(), FlowHelper.getFlowCreator(), dto.getArgs()).isPresent();
    }

    private FlwTask checkFlwTaskById(Long taskId) {
        FlwTask flwTask = flowLongEngine.queryService().getTask(taskId);
        ApiAssert.isEmpty(flwTask, "当前ID执行任务不存在");
        return flwTask;
    }

    @Override
    public boolean carbonCopy(TaskCarbonCopyDTO dto) {
        FlwTask flwTask = this.checkFlwTaskById(dto.getTaskId());
        List<SysUser> sysUsers = sysUserService.listByIds(dto.getUserIds());
        ApiAssert.isEmpty(sysUsers, "指定用户不存在");
        flowLongEngine.queryService().getCcTaskActorsByInstanceId(flwTask.getInstanceId()).ifPresent(t -> t.forEach(actor -> sysUsers.forEach(user -> {
            if (Objects.equals(actor.getActorId(), String.valueOf(user.getId()))) {
                ApiAssert.fail("用户【" + user.getUsername() + "】已抄送，请勿重复操作");
            }
        })));

        // 创建NodeAssignee列表用于抄送任务
        List<NodeAssignee> nodeAssignees = sysUsers.stream().map(t -> {
            NodeAssignee nodeAssignee = new NodeAssignee();
            nodeAssignee.setId(String.valueOf(t.getId()));
            nodeAssignee.setName(t.getUsername());
            return nodeAssignee;
        }).toList();
        
        // 传递抄送意见
        FlowHelper.setProcessApprovalOpinion(dto.getContent());

        // 创建抄送任务
        return flowLongEngine.createCcTask(flwTask, nodeAssignees, FlowHelper.getFlowCreator());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean transfer(TaskAssigneeDTO dto) {
        FlowHelper.setProcessApprovalOpinion(dto.getContent());
        // 传递干预操作标识
        FlowHelper.setTaskIntervene(dto.getIntervene());
        if (Objects.equals(0, dto.getType())) {
            // 转办
            TaskService taskService = flowLongEngine.taskService();
            return taskService.transferTask(dto.getTaskId(), FlowHelper.getFlowCreator(), dto.toFlowCreator());
        }

        // 委派
        TaskService taskService = flowLongEngine.taskService();
        return taskService.delegateTask(dto.getTaskId(), FlowHelper.getFlowCreator(), dto.toFlowCreator());
    }

    private FlwTask getFlwTask(Long taskId) {
        FlwTask flwTask = flowLongEngine.queryService().getTask(taskId);
        ApiAssert.isEmpty(flwTask, "指定ID任务已执行完成");
        return flwTask;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean comment(ProcessApprovalDTO dto) {
        return flwProcessApprovalService.comment(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    @ProcessNegotiation(description = "同意审批时处理协商流程")
    public boolean consent(TaskApprovalDTO dto) {
        // 传递干预操作标识
        FlowHelper.setTaskIntervene(dto.getIntervene());

        // 判断是否修改模型
        if (MapUtils.isNotEmpty(dto.getAssigneeMap())) {

            // 传递动态分配处理人员
            FlowDataTransfer.dynamicAssignee(Collections.unmodifiableMap(dto.getAssigneeMap()));
        }

        // 获取任务，保存表单
        FlwTask flwTask = this.getFlwTask(dto.getTaskId());
        List<FlwTaskActor> taskActorList = flowLongEngine.queryService().getTaskActorsByTaskId(flwTask.getId());
        FlowHelper.setProcessApprovalOpinion(dto.getContent());
        ApiAssert.fail(!flwProcessFormService.saveForm(flwTask.getInstanceId(), dto.getProcessForm()), "保存保单内容失败");
        FlowForm.argsTransfer(dto.getProcessForm());

        boolean result;
        // 委派审批
        if (TaskType.delegate.eq(flwTask.getTaskType())) {
            result = flowLongEngine.taskService().resolveTask(flwTask.getId(), FlowHelper.getFlowCreator());
        } else {
            // 普通审批
            result = flowLongEngine.executeTask(dto.getTaskId(), FlowHelper.getFlowCreator());
        }
        log.info("完成的任务:{}", JSON.toJSONString(flwTask));
        log.info("完成任务的参与人:{}", JSON.toJSONString(taskActorList));

        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean rejection(TaskApprovalDTO dto) {
        // 传递干预操作标识
        FlowHelper.setTaskIntervene(dto.getIntervene());

        FlwTask flwTask = this.getFlwTask(dto.getTaskId());
        FlowHelper.setProcessApprovalOpinion(dto.getContent());
        return flowLongEngine.executeRejectTask(flwTask, dto.getNodeKey(), FlowHelper.getFlowCreator(), dto.getArgs(), dto.isTermination()).isPresent();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean appendNode(TaskAppendNodeDTO dto) {
        FlwTask flwTask = this.getFlwTask(dto.getTaskId());
        FlowHelper.setProcessApprovalOpinion(dto.getContent());
        return flowLongEngine.executeAppendNodeModel(flwTask.getId(), dto.toNodeModel(), FlowHelper.getFlowCreator(), dto.getType() == 9);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean jump(TaskJumpDTO dto) {
        // 传递干预操作标识
        FlowHelper.setTaskIntervene(dto.getIntervene() && AuthUtil.isSuperAdmin());
        FlowHelper.setProcessApprovalOpinion(dto.getContent());
        return flowLongEngine.executeJumpTask(dto.getTaskId(), dto.getNodeKey(), FlowHelper.getFlowCreator());
    }

    @Override
    public Integer countPendingApproval() {
        UserSession userSession = UserSession.getLoginInfo();
        return flowlongMapper.selectCountPendingApproval(userSession.getUserId());
    }

    @Override
    public boolean urgeByInstanceId(Long instanceId) {
        flowLongEngine.queryService().getActiveTaskActorsByInstanceId(instanceId).ifPresent(taskActors -> {
            // 演示催办逻辑，提示当前用户，实际业务可以做一些其他处理，比如通过短信、邮件、站内信等方式提醒用户
            UserSession userSession = UserSession.getLoginInfo();
            String content = taskActors.stream().map(FlwTaskActor::getActorName).collect(Collectors.joining(", "));
            sseService.sendRemind(userSession.getId(), "流程催办", "流程催办消息，通知用户：" + content);
            List<Long> actorIds = taskActors.stream().filter(item -> item.getActorType() == 0).map(FlwTaskActor::getActorId).map(Long::parseLong).collect(Collectors.toList());
            MessageEvent messageEvent = new MessageEvent();
            messageEvent.setTitle("流程催办");
            messageEvent.setContent("流程催办消息，通知用户：" + content);
            messageEvent.setUserIds(actorIds);
            messageEvent.setCreateId(userSession.getId());
            messageEvent.setCreateBy(userSession.getUsername());
            messageEvent.setCategory(0);
            messageEvent.setBusinessType("remind");
            messageEvent.setBusinessId(instanceId);
            applicationEventPublisher.publishEvent(messageEvent);
        });
        return true;
    }

    @Override
    public boolean approvedParentNode(Long parentTaskId, String actorId) {
        return flowlongMapper.selectCountByParentTaskIdAndActorId(parentTaskId, actorId) > 0;
    }

    private static final String APPROVE = "APPROVE";

    private static final String REJECT = "REJECT";

    @Override
    public Boolean FeiShuApproval(ApprovalParam param) {
        log.info("飞书审批回调:{}", JSON.toJSONString(param));
        FlowHelper.setTaskIntervene(false);
        FlowHelper.setProcessApprovalOpinion(param.getReason());

        String actionType = param.getAction_type();
        FlowCreator flowCreator = FlowHelper.getFlowCreator();
        if (!StringUtils.isBlank(param.getToken())) {
            // 情况一：卡片操作，携带 action_callback_token（即我们下发的 sso token）
            FeiShuActionContext ctx = FeiShuActionContext.parse(param.getAction_context());

            FlwTask task = flowLongEngine.queryService().getTask(ctx.getTaskId());

            try {
                if (APPROVE.equals(actionType)) {
                    // 保存表单并执行同意
                    ContractEntity contract = contractService.getById(ctx.getContractId().intValue());
                    if (contract != null) {
                        flwProcessFormService.saveForm(task.getInstanceId(), contract.getContent());
                        FlowForm.argsTransfer(contract.getContent());
                    }
                    // 通过显式传入 flowCreator 或内部 FlowHelper.getFlowCreator()
                    flowLongEngine.executeTask(task.getId(), flowCreator);
                }

                if (REJECT.equals(actionType)) {
                    flowLongEngine.executeRejectTask(task, flowCreator);
                }
            } catch (Exception e) {
                log.error("飞书审批回调异常", e);
            }
        }
        if (!StringUtils.isBlank(param.getInstance_id()) && !StringUtils.isBlank(param.getTask_id())) {
            FlwTaskActor actor = taskActorMapper.selectById(Long.parseLong(param.getTask_id()));
            FlwTask task = flowLongEngine.queryService().getTask(actor.getTaskId());
            FlwInstance instance = flowLongEngine.queryService().getInstance(task.getInstanceId());
            if (null == instance || null == instance.getBusinessKey()) {
                log.warn("流程实例不存在或businessKey为空,无关联合同，实例ID: {}", task.getInstanceId());
                return true;
            }
            try {
                if (APPROVE.equals(actionType)) {
                    // 保存表单并执行同意
                    ContractEntity contract = contractService.getById(Integer.parseInt(instance.getBusinessKey()));
                    if (contract != null) {
                        flwProcessFormService.saveForm(task.getInstanceId(), contract.getContent());
                        FlowForm.argsTransfer(contract.getContent());
                    }
                    flowLongEngine.executeTask(task.getId(), flowCreator);
                }

                if (REJECT.equals(actionType)) {
                    flowLongEngine.executeRejectTask(task, flowCreator);
                }
            } catch (Exception e) {
                log.error("飞书审批回调异常", e);
            }
        }
        return true;
    }

    /**
     * 飞书默认审批回调(防止飞书审批代办堆积)
     *
     * @param param
     */
    @Override
    public void DefaultFeiShuApproval(ApprovalParam param) {
        FlwHisInstance histInstance = flowLongEngine.queryService().getHistInstance(Long.parseLong(param.getInstance_id()));
        int contractId = Integer.parseInt(histInstance.getBusinessKey());
        String contractName = contractFieldValueMapper.getFieldValueByCode(contractId, SystemFieldsEnum.CONTRACT_NAME.getCode());
        String contractNumber = contractFieldValueMapper.getFieldValueByCode(contractId, SystemFieldsEnum.CONTRACT_NUMBER.getCode());
        String contractType = contractFieldValueMapper.getFieldValueByCode(contractId, SystemFieldsEnum.CONTRACT_TYPE.getCode());
        ArrayList<SynchronizationApprovalDTO.Form> result = new ArrayList<>();
        result.add(new SynchronizationApprovalDTO.Form(SystemFieldsEnum.CONTRACT_NAME.getFieldName(), contractName));
        result.add(new SynchronizationApprovalDTO.Form(SystemFieldsEnum.CONTRACT_NUMBER.getFieldName(), contractNumber));
        result.add(new SynchronizationApprovalDTO.Form(SystemFieldsEnum.CONTRACT_TYPE.getFieldName(), contractType));
        feiShuConfigProperties.getApps().forEach((item, config) -> {
            try {
                SynchronizationApprovalDTO dto = new SynchronizationApprovalDTO();
                dto.setTenantKey(config.getTenantKey());
                dto.setApprovalCode(param.getApproval_code());
                dto.setApplyUserId(param.getUser_id());
                dto.setInstanceId(param.getInstance_id());
                dto.setTitle(contractName);
                dto.setInstanceStatus(FeiShuInstanceStatus.PENDING.getKey());
                dto.setApplyUserId(histInstance.getCreateId());
                dto.setStartTime(histInstance.getCreateTime());
                dto.setForms(result);
                dto.setUpdateTime(new Date());
                dto.setEndTime(null);
                SynchronizationApprovalDTO.Task feiShuTask = new SynchronizationApprovalDTO.Task();
                feiShuTask.setTaskId(param.getTask_id());
                feiShuTask.setTaskUserId(param.getUser_id());
                feiShuTask.setTaskStatus(FeiShuTaskStatus.DONE.getKey());
                feiShuTask.setExtra("{\"complete_reason\":\"approved\"}");
                feiShuTask.setStartTime(histInstance.getCreateTime());
                feiShuTask.setEndTime(new Date());
                feiShuTask.setUpdateTime(new Date());
                dto.setTasks(List.of(feiShuTask));
                feiShuApproval.synchronizationApproval(dto);
            } catch (Exception e) {
                log.error("飞书审批回调异常", e);
            }
        });
    }


    /**
     * 获取下个节点列表
     */
    private List<NodeModel> getNextNodeList(NodeRendering.Req dto) {
        FlwInstance instance = flowLongEngine.queryService().getInstance(dto.getInstanceId());
        if (instance == null) {
            //ApiAssert.fail(null == instance, "当前流程实例不存在");
            return Collections.emptyList();

        }
        FlwExtInstance extInstance = flowLongEngine.queryService().getExtInstance(dto.getInstanceId());
        NodeModel rootNodeModel = extInstance.model().getNodeConfig();
        // Fix null pointer exception: use full constructor to properly initialize engine field
        Execution execution = new Execution(flowLongEngine, extInstance.model(), FlowCreator.of(instance.getCreateId(), instance.getCreateBy()), instance, dto.getFormData());
        List<NodeModel> nodeModels = ModelHelper.getNextChildNodes(flowLongEngine.getContext(), execution, rootNodeModel, instance.getCurrentNodeKey(),instance.getCurrentNodeKey());
        if (null != nodeModels) {
            nodeModels = nodeModels.stream().map(NodeModel::cloneBaseInfo).toList();
        }
        return nodeModels;
    }


    private static class FeiShuActionContext {
        private Long contractId;
        private Long taskId;

        public Long getContractId() {
            return contractId;
        }

        public Long getTaskId() {
            return taskId;
        }

        static FeiShuActionContext parse(String actionContext) {
            String[] arr = actionContext == null ? new String[0] : actionContext.split(":");
            FeiShuActionContext ctx = new FeiShuActionContext();
            if (arr.length > 0 && org.apache.commons.lang3.StringUtils.isNotBlank(arr[0])) {
                ctx.contractId = Long.parseLong(arr[0]);
            }
            if (arr.length > 1 && org.apache.commons.lang3.StringUtils.isNotBlank(arr[1])) {
                ctx.taskId = Long.parseLong(arr[1]);
            }
            return ctx;
        }
    }

    /**
     * 解析单个节点的审批人信息
     */
    private void parseNodeAssignee(NodeModel nodeModel, Map<String, Object> assigneeMap) {
        if (nodeModel == null) {
            return;
        }

        // 检查当前节点是否有审批人配置
        if (nodeModel.getNodeAssigneeList() != null && !nodeModel.getNodeAssigneeList().isEmpty()) {
            Map<String, Object> nodeAssignee = new HashMap<>();

            // 根据节点类型确定type值
            Integer type = determineAssigneeType(nodeModel);
            nodeAssignee.put("type", type);

            // 构造assigneeList
            List<Map<String, Object>> assigneeList = new ArrayList<>();
            for (NodeAssignee assignee : nodeModel.getNodeAssigneeList()) {
                Map<String, Object> assigneeInfo = new HashMap<>();
                assigneeInfo.put("id", assignee.getId());
                assigneeInfo.put("name", assignee.getName());
                if (assignee.getWeight() != null) {
                    assigneeInfo.put("weight", assignee.getWeight());
                }
                if (assignee.getTenantId() != null) {
                    assigneeInfo.put("tenantId", assignee.getTenantId());
                }
                // 添加扩展配置（包含头像等信息）
                if (assignee.getExtendConfig() != null) {
                    assigneeInfo.put("extendConfig", assignee.getExtendConfig());
                }
                assigneeList.add(assigneeInfo);
            }
            nodeAssignee.put("assigneeList", assigneeList);

            assigneeMap.put(nodeModel.getNodeKey(), nodeAssignee);
        }
    }

    /**
     * 根据节点配置确定审批人类型
     */
    private Integer determineAssigneeType(NodeModel nodeModel) {
        if (nodeModel.getSetType() == null) {
            return 1; // 默认用户类型
        }

        String setType = nodeModel.getSetType().toString();
        switch (setType) {
            case "role":
                return 3; // 角色类型
            case "department":
                return 2; // 部门类型
            case "specifyMembers":
            case "initiatorSelected":
                // 根据选择模式确定类型
                if (nodeModel.getSelectMode() != null && nodeModel.getSelectMode() == 3) {
                    return 3; // 角色
                } else {
                    return 1; // 用户
                }
            default:
                return 1; // 默认用户类型
        }
    }


    /**
     * 根据任务类型确定合同状态
     *
     * @param taskType 任务类型
     * @return 合同状态
     */
    private String determineContractStatusByTaskType(Integer taskType) {
        if (taskType == null) {
            log.warn("任务类型为空，使用默认状态APPROVED");
            return ContractStatusEnum.APPROVED.getCode();
        }

        // 根据TaskType枚举判断
        if (TaskType.seal.eq(taskType)) {
            // 盖章节点(100) -> SEALED状态
            log.info("盖章节点审批完成，设置合同状态为SEALED");
            return ContractStatusEnum.SEALED.getCode();
        } else if (TaskType.archive.eq(taskType)) {
            // 归档节点(101) -> ARCHIVED状态
            log.info("归档节点审批完成，设置合同状态为ARCHIVED");
            return ContractStatusEnum.ARCHIVED.getCode();
        } else {
            // 其他节点 -> APPROVED状态
            log.info("普通审批节点完成，设置合同状态为APPROVED");
            return ContractStatusEnum.APPROVED.getCode();
        }
    }

    /**
     * 处理审批记录中的createBy字段，将用户名替换为真实姓名
     *
     * @param processApprovals 审批记录列表
     * @return 处理后的审批记录列表
     */
    private List<FlwProcessApproval> processApprovalRealNames(List<FlwProcessApproval> processApprovals) {
        if (processApprovals == null || processApprovals.isEmpty()) {
            return processApprovals;
        }

        try {
            // 收集所有需要查询的用户ID
            Set<Long> userIds = processApprovals.stream().filter(approval -> approval.getCreateId() != null).map(FlwProcessApproval::getCreateId).collect(Collectors.toSet());

            if (userIds.isEmpty()) {
                log.debug("没有需要查询真实姓名的用户ID");
                return processApprovals;
            }

            // 批量查询用户真实姓名
            Map<Long, String> userRealNameMap = new HashMap<>();
            for (Long userId : userIds) {
                try {
                    SysUser sysUser = sysUserService.getById(userId);
                    if (sysUser != null && sysUser.getRealName() != null) {
                        userRealNameMap.put(userId, sysUser.getRealName());
                    } else {
                        log.warn("未找到用户或用户真实姓名为空，用户ID: {}", userId);
                    }
                } catch (Exception e) {
                    log.error("查询用户真实姓名失败，用户ID: {}", userId, e);
                }
            }

            // 更新审批记录中的createBy字段
            for (FlwProcessApproval approval : processApprovals) {
                if (approval.getCreateId() != null) {
                    String realName = userRealNameMap.get(approval.getCreateId());
                    if (realName != null) {
                        approval.setCreateBy(realName);
                        log.debug("已更新用户{}的createBy为真实姓名: {}", approval.getCreateId(), realName);
                    } else {
                        log.debug("用户{}未找到真实姓名，保持原createBy值: {}", approval.getCreateId(), approval.getCreateBy());
                    }
                }
            }

            log.info("已处理{}条审批记录的用户真实姓名", processApprovals.size());

        } catch (Exception e) {
            log.error("处理审批记录真实姓名时发生异常", e);
            // 发生异常时返回原始列表，不影响主要功能
        }

        return processApprovals;
    }
}
